#include "pch.h"
#include "PixelBlurEffect.h"
#include "Engine.h"
#define  BUFFER_COUNT 2
namespace mini
{
	CPixelBlurEffect::CPixelBlurEffect()
	{
		auto pDevice = GEngine->getDevice();
		int nWidth = pDevice->getConfig().screenWidth;
		int nHeight = pDevice->getConfig().screenHeight;
		bindMaterial(R"(resource\Material\pixelBlur.ma)");
		SafeRelease(mpMeshUnit);
		mpMeshUnit = GEngine->createBillBoard(nWidth, nHeight);
		
		CMaterialUnit* pMaterialUnit = new CMaterialUnit;
		pMaterialUnit->setUnitFile(R"(resource\Material\pixelBlurPostEffect.ma)");
		pMaterialUnit->onInitialise();
		mpMeshUnit->bindMaterial(pMaterialUnit);

		//CTexture* pTexture = new CTexture();
		//pTexture->initialiseRenderTexture(nWidth, nHeight, DXGI_FORMAT_R32G32B32A32_FLOAT);
		//pTexture->setSampleState(pMaterialUnit->getSampler(0));
		//pMaterialUnit->setTexture(pTexture, 0);
		//mTextureArray.push_back(pTexture);
		for (int i = 0; i < BUFFER_COUNT; ++i)
		{
			CTexture* pTexture = new CTexture();
			if (nullptr != pTexture)
			{
				pTexture->initialiseRenderTexture(nWidth, nHeight, DXGI_FORMAT_R32G32B32A32_FLOAT);
				pTexture->setSampleState(pMaterialUnit->getSampler(i));
				pMaterialUnit->setTexture(pTexture, i);
				mTextureArray.push_back(pTexture);
			}
		}
		mpRenderTargetViewArray.push_back(mTextureArray[0]->getRenderTargetView());
		mpRenderTargetViewArray.push_back(mTextureArray[1]->getRenderTargetView());
		SafeRelease(pMaterialUnit);
	}

	CPixelBlurEffect::~CPixelBlurEffect()
	{
		SafeRelease(mpMeshUnit);
		for( auto item : mTextureArray )
		{
			SafeRelease(item);
		}
		mTextureArray.clear();
		mpRenderTargetViewArray.clear();
	}

	void CPixelBlurEffect::update(float fDeltaTime)
	{

	}
	
	void CPixelBlurEffect::commitToGpu(DeviceContext* pContext)
	{
		for( auto item : mTextureArray )
		{
			item->clearRenderTargetView(CPoint4F(0, 0, 0, 0));
		}
		pContext->OMSetRenderTargets(BUFFER_COUNT, &mpRenderTargetViewArray[0], nullptr);

		CShaderUnit* pShaderUnit = nullptr;
		auto _render = [&](std::map<CShaderUnit*, std::list<CMeshUnit*>>& renderUnit)
		{
			for (auto& item : renderUnit)
			{
				for (auto& child : (item.second))
				{
					auto pWorld = mLastWorldMT.find(child->getUnitID())->second;
					D3DXMatrixTranspose(&matrixArray[0], pWorld);
					D3DXMatrixTranspose(&matrixArray[1], GEngine->getViewMatrix());
					D3DXMatrixTranspose(&matrixArray[2], GEngine->getProjectMatrix());

					pShaderUnit->updateVSConstBuffer(5, matrixArray);
					pShaderUnit->setShader(pContext);
					pShaderUnit->setWorldMatrix(&child->getMatrix());
					pShaderUnit->setViewMatrix(GEngine->getViewMatrix());
					pShaderUnit->setProjectMatrix(GEngine->getProjectMatrix());
					pShaderUnit->apply(pContext);
					mpMaterialUnit->apply(pContext);
					child->render(pContext);
				}
			}
		};
		int nPassCount = mpMaterialUnit->getShaderUnitSize();
		for (int i = 0; i < nPassCount; ++i)
		{
			pShaderUnit = mpMaterialUnit->getShaderUnit(i);
			if (nullptr != pShaderUnit)
			{
				for (auto& item : mZbufferOffRenderUnits)
				{
					auto _item = (item.second);
					(_item.second)->render(pContext);
				}
				_render(mRenderUnits);
				_render(mAlphaRenderUnits);
			}
		}
		cleanUnit();

		if (mpMeshUnit)
		{
			GEngine->getDevice()->recoverBackBuffer(pContext);
			auto pMaterialUnit = mpMeshUnit->getMaterialUnit();
			auto pShaderUnit = pMaterialUnit->getShaderUnit(0);
			pShaderUnit->setWorldMatrix(&mpMeshUnit->getMatrix());
			pShaderUnit->setViewMatrix(GEngine->getViewMatrix());
			pShaderUnit->setOrthoMatrix(GEngine->getOrthoMatrix());
			pShaderUnit->setShader(pContext);
			pShaderUnit->apply(pContext);	
			mpMeshUnit->render(pContext);
		}
	}

	void CPixelBlurEffect::addUnit(CUnit* pUnit, EntityType Type, INT32 zLayer)
	{
		CMeshUnit* pMeshUnit = dynamic_cast<CMeshUnit*>(pUnit);
		if (pMeshUnit)
		{
			UINT32 id = pMeshUnit->getUnitID();
			mLastWorldMT[id] = &pMeshUnit->getMatrix();
		}
		CEffect::addUnit(pUnit, Type, zLayer);
	}

}